<template>
  <div class="ft-tab">
    <!-- 工具栏 + 表格滚动 + 底部分页/全选 -->
    <TabScaffold :current="pagination.current" :pageSize="pagination.pageSize" :total="total"
      :pageCount="pageData.length" :checkAll="checkAll" @update:current="(v) => pagination.current = v"
      @update:pageSize="(v) => pagination.pageSize = v" @check-all="onCheckAll">
      <!-- 工具栏（左） -->
      <template #toolbar-left>
        <a-space>
          <a-button @click="onAdd">新增</a-button>
          <a-button :disabled="!selectedRowKeys.length" @click="onBatchDelete">批量删除</a-button>
          <a-button @click="openImport">导入</a-button>
          <a-button :loading="exporting" @click="onExport">导出</a-button>
        </a-space>
      </template>

      <!-- 工具栏（右） -->
      <template #toolbar-right>
        <a-input-search v-model:value="keyword" placeholder="输入搜索" enter-button="搜索" @search="onSearch" allow-clear
          style="width: 260px" />
      </template>

      <!-- 表格主体 -->
      <div class="table-scroll">
        <a-table :columns="columns" :data-source="pageData" row-key="id" :pagination="false"
          :row-selection="rowSelection" :loading="loading" bordered class="table" :customRow="onCustomRow">
          <template #bodyCell="{ column, record }">
            <template v-if="column.key === 'name'">
              <!-- 改为纯文本，颜色黑色 -->
              <span class="name-text">{{ record.name }}</span>
            </template>

            <template v-else-if="column.key === 'status'">
              <span :class="['status', record.status === 'enabled' ? 'on' : 'off']">
                {{ record.status === 'enabled' ? '启用' : '停用' }}
              </span>
            </template>

            <template v-else-if="column.key === 'actions'">
              <span class="ops">
                <a @click="onEdit(record)">编辑</a>
                <span class="sep">|</span>
                <a @click="onDelete(record)" style="color: #ff4d4f;">删除</a>
                <span class="sep">|</span>
                <a v-if="record.status === 'enabled'" @click="onToggleStatus(record, 'disable')">停用</a>
                <span v-else class="disabled">停用</span>
                <span class="sep">|</span>
                <a v-if="record.status === 'disabled'" @click="onToggleStatus(record, 'enable')">启用</a>
                <span v-else class="disabled">启用</span>
              </span>
            </template>
          </template>
        </a-table>
      </div>
    </TabScaffold>

    <!-- 编辑弹窗 -->
    <a-modal v-model:visible="editVisible" :footer="null" title="编辑" :mask-closable="false" :keyboard="false" centered>
      <a-form :model="editForm" :label-col="{ style: 'width: 72px;' }" :wrapper-col="{ style: 'max-width: 420px;' }">
        <a-form-item label="名称："><a-input v-model:value="editForm.name" placeholder="请输入" /></a-form-item>
        <a-form-item label="状态：">
          <a-radio-group v-model:value="editForm.status">
            <a-radio value="enabled">启用</a-radio>
            <a-radio value="disabled">停用</a-radio>
          </a-radio-group>
        </a-form-item>
      </a-form>
      <div style="text-align:center;margin-top:12px">
        <a-button style="margin-right:8px" @click="editVisible = false">取消</a-button>
        <a-button type="primary" @click="onEditOk">确定</a-button>
      </div>
    </a-modal>

    <!-- 导入弹窗 -->
    <ImportModal v-model:modelValue="importVisible" title="禁查词导入" accept=".csv,.json" tip="说明：支持 CSV 或 JSON（UTF-8）。"
      @import="doImport" />

    <!-- 导出弹窗 -->
    <ExportModal v-model:modelValue="exportVisible" v-model:format="exportFormat" :loading="exporting" title="禁查词导出"
      @confirm="doExport" />
  </div>
</template>

<script lang="ts" setup>
import { computed, reactive, ref, onMounted, watch } from "vue";
import { useRouter } from "vue-router";
import type { Key } from "ant-design-vue/es/table/interface";
import type { TableRowSelection } from "ant-design-vue";
import { Modal, message } from "ant-design-vue";

/* === 引入骨架与弹窗组件 === */
import TabScaffold from "@/components/TabScaffold.vue";
import ImportModal from "@/components/ImportModal.vue";
import ExportModal from "@/components/ExportModal.vue";

import {
  getForbiddenList,
  deleteForbidden,
  deleteForbiddens,
  enableForbidden,
  disableForbidden,
  type ForbiddenItem,
  COLLECTION_FORBIDDEN,
  getCurrentUserId,
  importForbiddens,
} from "@/api/modules/forbiddenTerms.api";

const router = useRouter();
const TAB_KEY = "forbidden";

type Row = {
  id: string | number;
  name: string;
  query: string;
  status: "enabled" | "disabled";
};

/** 列表数据 */
const pageData = ref<Row[]>([]);
const total = ref(0);
const loading = ref(false);

/** 查询 / 分页 */
const keyword = ref("");
const pagination = reactive({ current: 1, pageSize: 10 });

const columns = [
  { title: "名称", dataIndex: "name", key: "name", width: 300 },
  { title: "状态", dataIndex: "status", key: "status", width: 160 },
  { title: "操作", key: "actions", width: 240 },
];


async function fetchList() {
  loading.value = true;
  try {
    const { list, total: t } = await getForbiddenList({
      page: pagination.current,
      pageSize: pagination.pageSize,
      keyword: keyword.value,
      sort: ["-id"],
      excludeStatus: "archived",
    });

    if ((list?.length ?? 0) === 0 && pagination.current > 1) {
      pagination.current = pagination.current - 1;
      return;
    }

    pageData.value = (list || []).map((it: ForbiddenItem) => ({
      id: it.id,
      name: it.query || "",
      query: it.query || "",
      status: it.status === "published" ? "enabled" : "disabled",
    }));
    total.value = t || 0;
    selectedRowKeys.value = [];
  } catch (e: any) {
    message.error(e?.message || "获取列表失败");
  } finally {
    loading.value = false;
  }
}
function onSearch() {
  pagination.current = 1;
  fetchList();
}
onMounted(fetchList);
watch(() => [pagination.current, pagination.pageSize], () => fetchList());

/** 选择 / 全选 */
const selectedRowKeys = ref<Key[]>([]);
const rowSelection = computed<TableRowSelection<Row>>(() => ({
  selectedRowKeys: selectedRowKeys.value,
  onChange: (keys: Key[]) => (selectedRowKeys.value = keys),
}));
const currentPageKeys = computed<Key[]>(() => pageData.value.map((r) => r.id));
const checkAll = computed(
  () => currentPageKeys.value.length > 0 && currentPageKeys.value.every((k) => selectedRowKeys.value.includes(k))
);
function onCheckAll(e: any) {
  const checked = e?.target?.checked;
  selectedRowKeys.value = checked
    ? Array.from(new Set([...selectedRowKeys.value, ...currentPageKeys.value]))
    : selectedRowKeys.value.filter((k) => !currentPageKeys.value.includes(k));
}

/** 跳转 */
function onAdd() {
  router.push({ path: "/ForbiddenTermsTabPage", query: { tab: TAB_KEY, mode: "create", backTo: "tab" } });
}
function onEdit(row: Row) {
  router.push({
    path: "/ForbiddenTermsTabPage",
    query: { tab: TAB_KEY, mode: "edit", id: String(row.id), backTo: "tab", row: encodeURIComponent(JSON.stringify(row)) },
  });
}
function onNameClick(row: Row) {
  router.push({
    path: "/ForbiddenTermsTabInfo",
    query: { tab: TAB_KEY, id: String(row.id), backTo: "tab", row: encodeURIComponent(JSON.stringify(row)) },
  });
}

/** 整行点击（操作列除外） */
function onCustomRow(record: Row) {
  return {
    onClick: (e: MouseEvent) => {
      const target = e.target as HTMLElement;
      if (target && target.closest('.ops')) return; // 操作列内点击不跳转
      onNameClick(record); // 其余区域点击整行跳详情
    },
    style: { cursor: 'pointer' },
  } as any;
}

/** 其它操作 */
async function onBatchDelete() {
  if (!selectedRowKeys.value.length) return;
  Modal.confirm({
    title: "确认删除选中项？",
    okText: "删除",
    okType: "danger",
    cancelText: "取消",
    async onOk() {
      try {
        await deleteForbiddens(selectedRowKeys.value as Array<string | number>);
        message.success("删除成功");
        await fetchList();
      } catch (e: any) {
        message.error(e?.message || "删除失败");
      }
    },
  });
}
function onDelete(row: Row) {
  Modal.confirm({
    title: "确认删除该记录？",
    content: `将删除：${row.name}`,
    okText: "删除",
    okType: "danger",
    cancelText: "取消",
    async onOk() {
      try {
        await deleteForbidden(row.id);
        message.success("删除成功");
        await fetchList();
      } catch (e: any) {
        message.error(e?.message || "删除失败");
      }
    },
  });
}
async function onToggleStatus(row: Row, action: "enable" | "disable") {
  try {
    if (action === "enable") {
      await enableForbidden(row.id);
      row.status = "enabled";
      message.success("已启用");
    } else {
      await disableForbidden(row.id);
      row.status = "disabled";
      message.success("已停用");
    }
  } catch (e: any) {
    message.error(e?.message || "操作失败");
  }
}

/* 编辑弹窗 */
const editVisible = ref(false);
const editForm = reactive<{ name: string; status: "enabled" | "disabled" }>({ name: "", status: "enabled" });
function onEditOk() { editVisible.value = false; }

/* ===================== 导出 ===================== */
const exporting = ref(false);
const exportVisible = ref(false);
const exportFormat = ref<"csv" | "json">("csv");

function onExport() {
  if (!exporting.value) exportVisible.value = true;
}

async function doExport() {
  if (exporting.value) return;
  exporting.value = true;
  try {
    try { await getCurrentUserId(); } catch { /* ignore */ }

    let rows: Row[];
    if (selectedRowKeys.value.length) {
      const set = new Set(selectedRowKeys.value);
      rows = pageData.value.filter((r) => set.has(r.id as any));
    } else {
      rows = await fetchAllForExport();
    }

    const statusSet = new Set(rows.map((r) => r.status));
    const statusTag = statusSet.size === 1 ? (statusSet.has("enabled") ? "enabled" : "disabled") : "all";

    const exportRows = rows.map((r) => ({
      query: r.query,
      status: r.status === "enabled" ? "published" : "draft",
    }));

    const stamp = formatTime(new Date());
    const base = `${COLLECTION_FORBIDDEN}_${statusTag}_${stamp}`;

    if (exportFormat.value === "json") {
      const content = JSON.stringify(exportRows, null, 2);
      downloadFile(content, `${base}.json`, "application/json;charset=utf-8");
    } else {
      const content = toCSV(exportRows, ["query", "status"]);
      downloadFile(content, `${base}.csv`, "text/csv;charset=utf-8");
    }

    message.success("导出成功");
    exportVisible.value = false;
  } catch (e: any) {
    message.error(e?.message || "导出失败");
  } finally {
    exporting.value = false;
  }
}

async function fetchAllForExport(): Promise<Row[]> {
  const pageSize = 500;
  let cur = 1;
  const all: Row[] = [];

  const first = await getForbiddenList({
    page: cur, pageSize, keyword: keyword.value, sort: ["-id"], excludeStatus: "archived",
  });
  const totalCount = first.total || 0;
  all.push(
    ...first.list.map((it) => ({
      id: it.id,
      name: it.query || "",
      query: it.query || "",
      status: it.status === "published" ? "enabled" : "disabled",
    }))
  );

  const totalPages = Math.ceil(totalCount / pageSize);
  while (cur < totalPages) {
    cur += 1;
    const { list } = await getForbiddenList({
      page: cur, pageSize, keyword: keyword.value, sort: ["-id"], excludeStatus: "archived",
    });
    all.push(
      ...list.map((it) => ({
        id: it.id,
        name: it.query || "",
        query: it.query || "",
        status: it.status === "published" ? "enabled" : "disabled",
      }))
    );
  }
  return all;
}

function toCSV(data: Array<Record<string, any>>, columns: string[] = Object.keys(data[0] || {})): string {
  if (!data.length) return columns.join(",") + "\n";
  const esc = (v: any) => {
    const s = String(v ?? "");
    return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
  };
  const lines = [columns.join(","), ...data.map((row) => columns.map((c) => esc(row[c])).join(","))];
  return lines.join("\n");
}

function downloadFile(content: string, filename: string, mime: string) {
  const blob = new Blob([content], { type: mime });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

function formatTime(d: Date) {
  const pad = (n: number) => (n < 10 ? "0" + n : "" + n);
  return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}_${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
}

/* ===================== 导入 ===================== */
const importVisible = ref(false);
const importing = ref(false);

function openImport() { importVisible.value = true; }

/**  把已选 File 传进来 */
async function doImport(file: File) {
  if (!file) { message.warning("请先选择文件"); return; }
  importing.value = true;
  try {
    await importForbiddens(file, { filename: file.name });
    message.success("导入成功");
    importVisible.value = false;
    fetchList();
  } catch (e: any) {
    const code =
      e?.response?.data?.errors?.[0]?.extensions?.code ||
      e?.data?.errors?.[0]?.extensions?.code ||
      e?.code;
    if (code === "RECORD_NOT_UNIQUE") {
      message.error("检测到重复的值");
    } else {
      message.error(e?.message || "导入失败");
    }
  } finally {
    importing.value = false;
  }
}
</script>

<style lang="less" scoped>
.ft-tab {
  background: #fff;
  border-radius: 6px;
  min-width: 0;
}

/* 表格样式 */
.table-scroll {
  overflow: auto;
  min-height: 0;
}

.table {
  :deep(.ant-table) {
    border: 1px solid #d9d9d9;
  }

  :deep(.ant-table-thead>tr>th) {
    background: #f4f8fd;
    color: #333;
    border-color: #d9d9d9;
    font-weight: 600;
    height: 40px;
    padding: 8px 12px;
  }

  :deep(.ant-table-tbody>tr>td) {
    border-color: #d9d9d9;
    height: 40px;
    padding: 8px 12px;
  }

  /*  */
  :deep(.name-link) {
    color: #1677ff;
    cursor: pointer;
    text-decoration: none;
  }

  /* 名称：改为黑色文本 */
  :deep(.name-text) {
    color: #000;
  }

  :deep(.status.on) {
    color: #1f7a1f;
  }

  :deep(.status.off) {
    color: #999;
  }

  :deep(.ops .sep) {
    margin: 0 8px;
    color: #999;
  }

  :deep(.ops .disabled) {
    color: #c5c5c5 !important;
    cursor: not-allowed;
    pointer-events: none;
  }
}
</style>
